package Gameplay;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import ADTs.PointADT;
import Project.Main;
import Project.MyGraphics;
import Project.RMath;
/**
 * This class is a representation of OnScreenObjects,
 * and this class is also able the deal with the 
 * projectiles' and objects' collisions on the screen. 
 * 
 * @author	Brian Wetherbee
 * 			Ryan McNamara
 * 			Zeng Yang
 *
 */
public class OnScreenObject {
	protected Rectangle movementBounds; // movementBounds of a object(enemy/player)
	protected PointADT location; //the CENTER of the object on screen
	protected int radius; // radius of a object(enemy/player)
	private PointADT acceleration; //units / millisecond^2
	protected double maxAcceleration; //units / millisecond^2
	protected PointADT velocity; //units / millisecond
	protected double maxSpeed;
	protected Level currLevel; 
	protected double wallBouncing; //scale of 0 to 1 , 1 being the most
	
	private Image drawImage;
	protected double drawRotate;


	public OnScreenObject(){

	}
	//To draw a rectangle surrounding a circle.
	public void paint(Graphics g){
			
			/* g.fillRect(0, 0, 20, 20);

    Graphics2D g2 = (Graphics2D) g;

    g2.translate(50, 50);
    g2.rotate(30.0 * Math.PI / 180.0);

    g2.scale(2.0, 2.0);

    g.setColor(Color.red);

    g.fillRect(0, 0, 20, 20);*/
		if(drawImage != null){
			BufferedImage bi = new BufferedImage(drawImage.getWidth(null), drawImage.getHeight(null), BufferedImage.TYPE_INT_ARGB);
			Graphics2D picg = (Graphics2D)bi.getGraphics();
			picg.rotate(drawRotate,drawImage.getWidth(null) / 2, drawImage.getHeight(null) / 2);
			
			picg.drawImage(drawImage,0,0,null);
			Image adjDrawImage = (Image)bi;
			
			
			bi = new BufferedImage(adjDrawImage.getWidth(null), adjDrawImage.getHeight(null), BufferedImage.TYPE_INT_ARGB);
			picg = (Graphics2D)bi.getGraphics();
			double sx = Main.internalToActualX(radius*2) / drawImage.getWidth(null);
			double sy = Main.internalToActualY(radius*2) / drawImage.getHeight(null);
			picg.scale(sx,sy);
			
			picg.drawImage(adjDrawImage,0,0,null);
			adjDrawImage = (Image)bi;
			

	        g.drawImage(adjDrawImage, (int)(location.getX() - radius),(int)(location.getY() - radius), null);
			return;
		}/*
		if(this.scaledDrawImage != null && false){
			Graphics2D g2d = (Graphics2D) gg;

			// set the translation to the mid of the component
			AffineTransform aff = new AffineTransform();
			
			int xloc = (int) (Main.internalToActualX(location.getX()) - scaledDrawImage.getWidth(null) / 2);
			int yloc = (int) (Main.internalToActualY(location.getY()) - scaledDrawImage.getHeight(null) / 2);
			aff.setToTranslation(xloc,yloc);

			// rotate with the rotation point as the mid of the image
			aff.rotate(drawRotate,
					scaledDrawImage.getWidth(null) / 2,scaledDrawImage.getHeight(null) / 2);

			// draw the image using the AffineTransform
	        g2d.drawImage(scaledDrawImage, aff, null);
		}*/
		g.setColor(Color.YELLOW);
		g.drawRect((int)(location.getX()-getRadius()),(int)( location.getY()-getRadius()),
				getRadius()*2,getRadius()*2);
	}

	//move an object by its velocity of its acceleration
	public boolean move(){
		//scale acceleration
		if(getAcceleration().getMagnitude() > maxAcceleration){
			getAcceleration().scaleToMagnitude(maxAcceleration);
		}

		velocity.xAdd(getAcceleration().getX() * currLevel.getFrameDuration());//add velocity on its x direction
		velocity.yAdd(getAcceleration().getY() * currLevel.getFrameDuration());//add velocity on its y direction

		if(velocity.getMagnitude() > maxSpeed){
			velocity.scaleToMagnitude(maxSpeed);
		}

		//changing its location by its velocity for each of frame durations.
		location.xAdd(velocity.getX()*currLevel.getFrameDuration());
		location.yAdd(-velocity.getY()*currLevel.getFrameDuration());
		return handleWallCollisions();
	}
	//This is collisions handling method
	protected boolean handleWallCollisions() {
		if(!movementBounds.contains(new Rectangle((int)location.getX()-getRadius(),(int)location.getY()-getRadius(),getRadius()*2,getRadius()*2))){

			if(location.getX() < (movementBounds.getMinX()+getRadius())){
				//location.setX(movementBounds.x + (movementBounds.x - (location.getX()-radius) + radius));
				location.setX(2*movementBounds.getMinX() - location.getX() + 2*getRadius());
				velocity.setX(-velocity.getX()*wallBouncing);
			}
			if(location.getX() > movementBounds.getMaxX()-getRadius()){
				//location.setX(movementBounds.getMaxX()-(location.getX() - movementBounds.getMaxX() + radius) - radius);
				location.setX(2*movementBounds.getMaxX()-location.getX() - 2 * getRadius());
				velocity.setX(-velocity.getX()*wallBouncing);
			}
			if(location.getY() < movementBounds.getMinY()+getRadius()){
				//location.setY(movementBounds.y + (movementBounds.y - (location.getY()-radius) + radius));
				location.setY(2*movementBounds.getMinY() - location.getY() + 2*getRadius());
				velocity.setY(-velocity.getY()*wallBouncing);
			}
			if(location.getY() > movementBounds.getMaxY()-getRadius()){
				//location.setY(movementBounds.getMaxY()-(location.getY() - movementBounds.getMaxY() + radius) - radius);
				location.setY(2*movementBounds.getMaxY()-location.getY() - 2 * getRadius());
				velocity.setY(-velocity.getY()*wallBouncing);
			}
			handleWallCollisions();
			return false;
		}
		return true;

	}

	public PointADT /*@ pure @*/ getLocation(){
		return location;
	}
	//@ requires acceleration != null;
	//@ ensures this.acceleration == acceleration.
	public void setAcceleration(PointADT acceleration) {
		this.acceleration = acceleration;
	}

	public PointADT getAcceleration() {
		return acceleration;
	}


	public int getRadius() {
		return radius;
	}
	public void setDrawImage(Image drawImage) {
		this.drawImage = drawImage;
		
	}
	public Image getDrawImage() {
		return drawImage;
	}
}
